From cad7c6b87bdc04f95e9706ef99de0b5685e10857 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 9 May 2011 09:46:02 +0100 Subject: [PATCH] misc cpufreq cleanup - proper handling of governor command line options when using the default governor - warning message for unrecognized command line options - replacing a NR_CPUS sized array with per-CPU data - a couple of __read_mostly annotations Signed-off-by: Jan Beulich --- xen/drivers/cpufreq/cpufreq.c | 16 +++--- xen/drivers/cpufreq/cpufreq_misc_governors.c | 52 ++++++++++++++------ xen/drivers/cpufreq/cpufreq_ondemand.c | 5 +- xen/include/acpi/cpufreq/cpufreq.h | 2 +- 4 files changed, 53 insertions(+), 22 deletions(-) diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c index a8290457c8..a44a444580 100644 --- a/xen/drivers/cpufreq/cpufreq.c +++ b/xen/drivers/cpufreq/cpufreq.c @@ -47,7 +47,8 @@ #include #include -static unsigned int usr_max_freq, usr_min_freq; +static unsigned int __read_mostly usr_min_freq; +static unsigned int __read_mostly usr_max_freq; static void cpufreq_cmdline_common_para(struct cpufreq_policy *new_policy); struct cpufreq_dom { @@ -55,10 +56,10 @@ struct cpufreq_dom { cpumask_t map; struct list_head node; }; -static LIST_HEAD(cpufreq_dom_list_head); +static LIST_HEAD_READ_MOSTLY(cpufreq_dom_list_head); -struct cpufreq_governor *cpufreq_opt_governor; -LIST_HEAD(cpufreq_governor_list); +struct cpufreq_governor *__read_mostly cpufreq_opt_governor; +LIST_HEAD_READ_MOSTLY(cpufreq_governor_list); bool_t __read_mostly cpufreq_verbose; @@ -525,6 +526,7 @@ void __init cpufreq_cmdline_parse(char *str) { static struct cpufreq_governor *__initdata cpufreq_governors[] = { + CPUFREQ_DEFAULT_GOVERNOR, &cpufreq_gov_userspace, &cpufreq_gov_dbs, &cpufreq_gov_performance, @@ -558,8 +560,10 @@ void __init cpufreq_cmdline_parse(char *str) } if (str && !cpufreq_handle_common_option(str, val) && - cpufreq_governors[gov_index]->handle_option) - cpufreq_governors[gov_index]->handle_option(str, val); + (!cpufreq_governors[gov_index]->handle_option || + !cpufreq_governors[gov_index]->handle_option(str, val))) + printk(XENLOG_WARNING "cpufreq/%s: option '%s' not recognized\n", + cpufreq_governors[gov_index]->name, str); str = end; } while (str); diff --git a/xen/drivers/cpufreq/cpufreq_misc_governors.c b/xen/drivers/cpufreq/cpufreq_misc_governors.c index 786854363d..746bbcd5ff 100644 --- a/xen/drivers/cpufreq/cpufreq_misc_governors.c +++ b/xen/drivers/cpufreq/cpufreq_misc_governors.c @@ -14,14 +14,17 @@ * */ +#include #include +#include #include #include /* * cpufreq userspace governor */ -static unsigned int cpu_set_freq[NR_CPUS]; +static unsigned int __read_mostly userspace_cmdline_freq; +static DEFINE_PER_CPU(unsigned int, cpu_set_freq); static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int event) @@ -35,21 +38,21 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: - if (!cpu_set_freq[cpu]) - cpu_set_freq[cpu] = policy->cur; + if (!per_cpu(cpu_set_freq, cpu)) + per_cpu(cpu_set_freq, cpu) = policy->cur; break; case CPUFREQ_GOV_STOP: - cpu_set_freq[cpu] = 0; + per_cpu(cpu_set_freq, cpu) = 0; break; case CPUFREQ_GOV_LIMITS: - if (policy->max < cpu_set_freq[cpu]) + if (policy->max < per_cpu(cpu_set_freq, cpu)) ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - else if (policy->min > cpu_set_freq[cpu]) + else if (policy->min > per_cpu(cpu_set_freq, cpu)) ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); else - ret = __cpufreq_driver_target(policy, cpu_set_freq[cpu], + ret = __cpufreq_driver_target(policy, per_cpu(cpu_set_freq, cpu), CPUFREQ_RELATION_L); break; @@ -68,7 +71,7 @@ int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq) if (!cpu_online(cpu) || !(policy = per_cpu(cpufreq_cpu_policy, cpu))) return -EINVAL; - cpu_set_freq[cpu] = freq; + per_cpu(cpu_set_freq, cpu) = freq; if (freq < policy->min) freq = policy->min; @@ -78,19 +81,35 @@ int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq) return __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); } -static void __init +static bool_t __init cpufreq_userspace_handle_option(const char *name, const char *val) { if (!strcmp(name, "speed") && val) { - unsigned int usr_cmdline_freq; - unsigned int cpu; + userspace_cmdline_freq = simple_strtoul(val, NULL, 0); + return 1; + } + return 0; +} - usr_cmdline_freq = simple_strtoul(val, NULL, 0); - for (cpu = 0; cpu < NR_CPUS; cpu++) - cpu_set_freq[cpu] = usr_cmdline_freq; +static int cpufreq_userspace_cpu_callback( + struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + switch (action) + { + case CPU_UP_PREPARE: + per_cpu(cpu_set_freq, cpu) = userspace_cmdline_freq; + break; } + + return NOTIFY_DONE; } +static struct notifier_block cpufreq_userspace_cpu_nfb = { + .notifier_call = cpufreq_userspace_cpu_callback +}; + struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, @@ -99,6 +118,11 @@ struct cpufreq_governor cpufreq_gov_userspace = { static int __init cpufreq_gov_userspace_init(void) { + unsigned int cpu; + + for_each_online_cpu(cpu) + per_cpu(cpu_set_freq, cpu) = userspace_cmdline_freq; + register_cpu_notifier(&cpufreq_userspace_cpu_nfb); return cpufreq_register_governor(&cpufreq_gov_userspace); } __initcall(cpufreq_gov_userspace_init); diff --git a/xen/drivers/cpufreq/cpufreq_ondemand.c b/xen/drivers/cpufreq/cpufreq_ondemand.c index 77b5dfc4fd..ddffc7cc38 100644 --- a/xen/drivers/cpufreq/cpufreq_ondemand.c +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c @@ -296,7 +296,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event) return 0; } -static void __init cpufreq_dbs_handle_option(const char *name, const char *val) +static bool_t __init cpufreq_dbs_handle_option(const char *name, const char *val) { if ( !strcmp(name, "rate") && val ) { @@ -334,6 +334,9 @@ static void __init cpufreq_dbs_handle_option(const char *name, const char *val) } dbs_tuners_ins.powersave_bias = tmp; } + else + return 0; + return 1; } struct cpufreq_governor cpufreq_gov_dbs = { diff --git a/xen/include/acpi/cpufreq/cpufreq.h b/xen/include/acpi/cpufreq/cpufreq.h index 3554896ef7..c93aeeeae7 100644 --- a/xen/include/acpi/cpufreq/cpufreq.h +++ b/xen/include/acpi/cpufreq/cpufreq.h @@ -93,7 +93,7 @@ struct cpufreq_governor { char name[CPUFREQ_NAME_LEN]; int (*governor)(struct cpufreq_policy *policy, unsigned int event); - void (*handle_option)(const char *name, const char *value); + bool_t (*handle_option)(const char *name, const char *value); struct list_head governor_list; }; -- 2.30.2